import { _decorator, Color, Component, instantiate, Label, Layout, Node, Prefab, ProgressBar, Sprite, tween, v3, Vec3 } from 'cc';
import { Report } from '../entity/Report';
import { FightManager } from './FightManager';
import { OperationItem } from '../entity/OperationItem';
import { EventManager } from '../event/EventManager';
import { CardController } from './CardController';
import { OperationType } from '../entity/OperationType';
import { SkillStateEnum } from '../entity/SkillStateEnum';
import { UIManager } from '../common/UIManager';
import { AttrChangedType } from '../entity/AttrChangedType';
import { FightCover } from './FightCover';
import { PrefabEnum } from '../common/PrefabEnum';
import { FightVictory } from './FightVictory';
import { FightFail } from './FightFail';
import { UserInfo } from '../common/UserInfo';
const { ccclass, property } = _decorator;

@ccclass('FightController')
export class FightController extends Component {

    static instance: FightController
    protected onLoad(): void {
        FightController.instance = this;
    }
    @property(FightCover)
    fightCover: FightCover
    @property(Node)
    back: Node

    @property(Node)
    myLayout: Node
    @property(Node)
    enemyLayout: Node
    @property(Label)
    myName: Label
    @property(Label)
    enemyName: Label
    @property(ProgressBar)
    myHP: ProgressBar
    @property(ProgressBar)
    enemyHP: ProgressBar
    @property(Node)
    myWarning: Node
    @property(Node)
    enemyWarning: Node
    @property(Sprite)
    myHead:Sprite
    @property(Sprite)
    enemyHead:Sprite
   

    @property(Label)
    desc: Label
    @property(Prefab)
    card: Prefab

    report: Report

    private operation: OperationItem[] = []


    startOp: OperationItem
    heroList: OperationItem[]

    myCardList: CardController[] = []
    enemyCardList: CardController[] = []

    private _meId: number
    private _enemyId: number
    private _meName: string
    private _enemyName: string

    private _time: number = 3
    /**已经播放过了的动作 */
    playedIds: number[] = []

    async start() {
        this.back.on(Node.EventType.TOUCH_END, () => {
            UIManager.instance.loadScene('village')
        }, this)


        this.report = FightManager.instance.report


        let rs = JSON.parse(this.report.content);
        let names = JSON.parse(this.report.rParam);

        console.log(names)



        for (let item of rs) {

            console.log(item)
            if (item.PreCondition != null) {
                let op = new OperationItem(item)
                op.translate(names)

                switch (op.type) {
                    case OperationType.Start:
                        this.setStart(op)
                        break
                    case OperationType.Enter:
                        this.setEnter(op)
                        break
                    default:
                        this.operation.push(op);
                }


            }

        }


        // this.playCover()

        await this.fightCover.playCover()
        this.play()

        // this.setDesc(this._time + '')
        // this.schedule(this.countDown, 1, this._time - 1)


    }

    setHP() {
        let count = 0
        let cur = 0
        for (let item of this.myLayout.children) {
            let controller = item.getComponent(CardController)
            count += controller.maxLife
            cur += controller.life

        }
        this.myHP.progress = cur / count
        if (this.myHP.progress < 0.2) {
            this.myWarning.active = true
        }

        count = 0
        cur = 0
        for (let item of this.enemyLayout.children) {
            let controller = item.getComponent(CardController)
            count += controller.maxLife
            cur += controller.life
        }
        this.enemyHP.progress = cur / count
        if (this.enemyHP.progress < 0.2) {
            this.enemyWarning.active = true
        }
    }

    setStart(op: OperationItem) {
        if (op.params.me == UserInfo.instance.villageData.uid) {
            this._meId = op.params.me
            this._enemyId = op.params.enemy
        } else {
            this._meId = op.params.enemy
            this._enemyId = op.params.me
        }



        let names = JSON.parse(this.report.rParam);
        this._meName = names[this._meId]
        this._enemyName = names[this._enemyId]

        this.myName.string = this._meName
        this.enemyName.string = this._enemyName
    }

    setEnter(op: OperationItem) {
        let userId = op.params.sInfo[0]
        let index = op.params.sInfo[2]




        if (userId == this._meId) {

            let node = this.myLayout.children[index]
            node.getComponent(Sprite).color = Color.WHITE
            let controller = node.getComponent(CardController)
            controller.setData(op)
        } else {

            let node = this.enemyLayout.children[index]
            node.getComponent(Sprite).color = Color.WHITE
            let controller = node.getComponent(CardController)
            controller.setData(op)
        }
    }

    countDown() {
        this._time--

        if (this._time == 0) {
            this.setDesc('开始')

            this.scheduleOnce(() => {
                this.setDesc('')
                this.play()
            }, 1)
            return
        }
        this.setDesc(this._time + '')


    }

    setDesc(str) {
        this.desc.string = str
        tween(this.desc.node)
            .to(0.2, { scale: new Vec3(2, 2, 2) },)
            .to(0.5, { scale: new Vec3(1, 1, 1) })
            .start()
    }

    async play() {


        for (let op of this.operation) {

            console.log(op.EventIndex, op.params.desc)
            console.log(op)

            switch (op.type) {
                case OperationType.End:

                    // this.setDesc(op.params.desc)
                    await this.playEnd(op)
                    break
                case OperationType.Skill:
                    await this.playSkill(op)
                    break
                case OperationType.AttrChanged:
                    await this.playAttrChanged(op)
                    break
                case OperationType.Dead:
                    await this.playDead(op)
                    break
                case OperationType.Alive:
                    await this.playAlive(op)
                    break
                case OperationType.Notify:
                    await this.playNotify(op)
                    break
                case OperationType.BuffChanged:
                    await this.playBuffChanged(op)
                    break
                case OperationType.Combo:
                    await this.playCombo(op)
                    break
                case OperationType.ComboReady:
                    await this.playComboReady(op)
                    break
                case OperationType.Disappear:

                    break
                case OperationType.Effect:
                    await this.playEffect(op)
                    break
            }

            // await new Promise((resolve) => {
            //     this.scheduleOnce(() => {
            //         resolve(true)
            //     }, 0.5)
            // })

            this.setHP()

        }
    }

    getCardController(op: OperationItem): CardController {
        let userId = op.params.sInfo[0]
        let position = op.params.sInfo[2]
        let card: Node
        if (userId == this._meId) {
            card = this.myLayout.children[position]
        } else {
            card = this.enemyLayout.children[position]
        }
        let controller = card?.getComponent(CardController)
        return controller
    }

    getCard(userId: number, heroId: number): Node {
        let card: Node
        if (userId == this._meId) {
            for(let ch of this.myLayout.children){
                let id = ch.getComponent(CardController).heroId
                if(id == heroId){
                    card = ch
                }
            }
           
        } else {
            for(let ch of this.enemyLayout.children){
                let id = ch.getComponent(CardController).heroId
                if(id == heroId){
                    card = ch
                }
            }
            
        }
        return card
    }

    async playSkill(op: OperationItem) {

        let controller = this.getCardController(op)

        switch (op.params.state) {
            case SkillStateEnum.Ready:
                await controller?.playReady(op)
                break;
            case SkillStateEnum.Start:
                await controller?.playStart(op)
                break;
            case SkillStateEnum.Cancel:
                await controller?.playCancel(op)
                break;
            case SkillStateEnum.End:
                await controller?.playEnd(op)
                break;
        }
    }

    async playBuffChanged(op: OperationItem) {

        let controller = this.getCardController(op)
        await controller?.playBuffChanged(op)
    }

    async playAttrChanged(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playAttrChanged(op)
    }

    async playDead(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playDead(op)
    }

    async playAlive(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playAlive(op)
    }

    async playCombo(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playCombo(op)
    }

    async playComboReady(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playComboReady(op)
    }

    async playEffect(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playEffect(op)
    }

    async playNotify(op: OperationItem) {
        let controller = this.getCardController(op)
        await controller?.playNotify(op)
    }

    async playEnd(op: OperationItem) {
        let desc = ''
        let victory = false
        if (op.params.me == UserInfo.instance.villageData.uid) {
            victory = op.params.victory
        } else {
            victory = !op.params.victory
        }


        if (op.params.oa && op.params.ob) {
            if (victory) {
                desc = `士气上升${Math.min(50, 100 * (op.params.a / op.params.oa) / 2).toFixed(0)}%`
            } else {
                desc = `士气下降${Math.min(50, 100 * (op.params.b / op.params.ob) / 2).toFixed(0)}%`
            }

        } else {
            if (victory) {
                desc = '士气上升0%'
            } else {
                desc = '士气下降0%'
            }

        }

        if (victory) {
            let ui = await UIManager.instance.openUI(PrefabEnum.FightVictory)
            ui.getComponent(FightVictory).open(desc)

          
            this.enemyHead.grayscale = true

        } else {
            let ui = await UIManager.instance.openUI(PrefabEnum.FightFail)
            ui.getComponent(FightFail).open(desc)

              this.myHead.grayscale =true
        }

        this.scheduleOnce(() => {
            this.myWarning.active = false
            this.enemyWarning.active = false
        }, 1)


    }
    /**是否暴击 */
    isBang(index: number, heroId: number): boolean {
        let bang = false
        let start = false
        for (let op of this.operation) {
            if (index == op.EventIndex) {
                start = true
            }

            if (!start) {
                continue
            }

            if (op.type == OperationType.AttrChanged && op.params.hid == heroId) {
                bang = op.params.type == AttrChangedType.Bang
                break
            }
        }

        return bang
    }



}


